﻿namespace Example.Diagnostics
{
    using System.Diagnostics;
    using System.Diagnostics.CodeAnalysis;

    public static class PerformanceCounters
    {
        private const string AverageTimerBaseCounterName = "Average Example Time Base";

        private const string AverageTimerCounterName = "Average Example Time";

        private const string CategoryName = "Example Category";

        private const string MachineName = ".";

        private const string RateOfCountsPerSecondCounterName = "Example counters / sec";

        [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "It is the responsibility of the calling code to dispose correctly.")]
        private static PerformanceCounter AverageTimerBaseCounter
        {
            get
            {
                Trace.Assert(
                    PerformanceCounterCategory.CounterExists(AverageTimerBaseCounterName, CategoryName),
                    "The AverageTimer32 base counter was not found in \"Example Category\".");

                var result = new PerformanceCounter(CategoryName, AverageTimerBaseCounterName, false)
                {
                    MachineName = MachineName
                };

                return result;
            }
        }

        [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "It is the responsibility of the calling code to dispose correctly.")]
        private static PerformanceCounter AverageTimerCounter
        {
            get
            {
                Trace.Assert(
                    PerformanceCounterCategory.CounterExists(AverageTimerCounterName, CategoryName),
                    "The AverageTimer32 counter was not found in \"Example Category\".");

                var result = new PerformanceCounter(CategoryName, AverageTimerCounterName, false)
                {
                    MachineName = MachineName
                };

                return result;
            }
        }

        [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "It is the responsibility of the calling code to dispose correctly.")]
        private static PerformanceCounter RateOfCountsPerSecondCounter
        {
            get
            {
                Trace.Assert(
                    PerformanceCounterCategory.CounterExists(RateOfCountsPerSecondCounterName, CategoryName),
                    "The RateOfCountsPerSecond32 counter was not found in \"Example Category\".");

                var result = new PerformanceCounter(CategoryName, RateOfCountsPerSecondCounterName, false)
                {
                    MachineName = MachineName
                };

                return result;
            }
        }

        public static void AverageTime(long ticks)
        {
            using (var counter = AverageTimerCounter)
            {
                counter.IncrementBy(ticks);
            }

            using (var counter = AverageTimerBaseCounter)
            {
                counter.Increment();
            }
        }

        public static void RateOfCountsPerSecond()
        {
            using (var counter = RateOfCountsPerSecondCounter)
            {
                counter.Increment();
            }
        }
    }
}